#include <iostream>
#include <cstdio>
#include<cstdlib>
#include <cassert>
#include<ctime>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string>
#include <cstring>
#include<functional>
#include<vector>
#define PROCESS_NUM 5
#define Make_Seed()  srand((unsigned long)time(nullptr)^getpid()^rand()%1024)
using namespace std;

//函数指针 类型
typedef void(*func_t)();

void downloadTask()
{
    cout<<getpid()<<": 下载任务"<<endl;
    sleep(1);
}
void IOTask()
{
    cout<<getpid()<<": IO任务"<<endl;
    sleep(1);
}
void flushTask()
{
    cout<<getpid()<<": 刷新任务"<<endl;
    sleep(1);
}
void loadTaskFunc(vector<func_t> *out)
{
    assert(out);
    out->push_back(downloadTask);
    out->push_back(IOTask);
    out->push_back(flushTask);
    
    
}

class subEp //EndPoint
{
public:
    subEp(pid_t subId,int writeFd)
    :
    _subId(subId),
    _writeFd(writeFd)
    {
        char nameBuffer[1024];
        snprintf(nameBuffer,sizeof nameBuffer,"process-%d[pid(%d)-fd(%d)]",num++,_subId,_writeFd);
        _name=nameBuffer;
    }
public:
    static int num;
    string _name;
    pid_t _subId;
    int _writeFd;

};
int subEp::num=0;
int recvTask(int readFd)
{
    int code=0;
    ssize_t s=read(readFd,&code,sizeof(code));
    //assert(s==sizeof(int));
    if(s==4) return code;
    else if(s<=0) return -1;
    else return 0;


}
void createSubProcess(vector<subEp> *subs,vector<func_t>& funcMap)
{
    for(int i=0;i<PROCESS_NUM;i++)
    {
        int fds[2];
        int n=pipe(fds);
        assert(n==0);
        (void)n; 
        pid_t id=fork();
        if(id==0)
        {
            //子进程 处理任务
            close(fds[1]);
            while(true)
            {
                //获取命令码 若没有发送 子进程应该阻塞
                int commandCode=recvTask(fds[0]);
                //完成任务
                if(commandCode>=0&&commandCode<funcMap.size())
                funcMap[commandCode]();
                else if(commandCode==-1) break;
                //cout<<"sub recive code error"<<endl;
            }

            exit(0);
        }
        close(fds[0]);
        subEp sub(id,fds[1]);
        subs->push_back(sub);
    }
}

void sendTask(const subEp &process,int taskNum)
{
    cout<<"send task num: "<<taskNum<<" send to ->"<<process._name <<endl;
    int n=write(process._writeFd,&taskNum,sizeof(taskNum));
    assert(n==sizeof(int));
    (void)n;   

}

void loadBlanceControl(const vector<subEp> &subs,vector<func_t>& funcMap,int count)
{
    int processnum=subs.size();
    int tasknum=funcMap.size();
    bool forever=(count==-1? true:false);

    while(true)
    {
        if(forever==false)
        {
            
            if(count==0) break;
            count--;           
        }
        //选择一个子进程 --> vector<subEp> subs -> index 随机数
        int sub_Idx=rand()%processnum;
        //选择一个任务 --> vector<func_t> funcMap ->index 随机数
        int task_Idx=rand()%tasknum;

        //任务发送给所选进程
        sendTask(subs[sub_Idx],task_Idx);
        sleep(2);
        
    }
    //写入端关闭 读取端读到0
    for(int i=0;i<processnum;i++)
    close(subs[i]._writeFd);

}

void waitProcess(vector<subEp> processes)
{
    int processnum=processes.size();
    for(int i=0;i<processnum;i++)
    {
        waitpid(processes[i]._subId,nullptr,0);
        cout<<"wait sub process sucess ... :"<<processes[i]._subId<<endl;

    }
}
int main()
{
    
    Make_Seed();
    //1.建立子进程和子进程通信的管道
    //1.1加载方法表
    vector<func_t> funcMap;
    loadTaskFunc(&funcMap);
    //1.2创建子进程 并且维护 父子通信信道
    vector<subEp> subs;
    createSubProcess(&subs,funcMap);
    
    

    // 2.父进程 控制子进程 负载均衡的向子进程发送命令码
    int taskCnt=3; //-1代表无休止进行
    loadBlanceControl(subs,funcMap,taskCnt);
    

    //3.回收子进程信息
    waitProcess(subs);

    return 0;
}